/*
    This file is part of MOOPerformanceAssessment.

    MOOPerformanceAssessment is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    MOOPerformanceAssessment is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MOOPerformanceAssessment; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Authors: Thomas Voß, 2007
    Contact: thomas.voss.bochum@googlemail.com
*/

#include "../include/MOOPerformanceAssessmentConfig.h"

#include "../include/IClass.h"
#include "../include/IDataSetReader.h"
#include "../include/IFileNameAssembler.h"
#include "../include/IPostProcessor.h"

#include <QLibrary>
#include <QSettings>

#include <sstream>

typedef IBinaryQualityIndicator* 	(*BinaryQualityIndicatorFactory)();
typedef IDataSetReader* 		(*DataSetReaderFactory)();
typedef IFileNameAssembler* 		(*FileNameAssemblerFactory)();
typedef IPostProcessor*			(*IPostProcessorFactory)();
typedef IStatisticalSignificanceTest*	(*StatisticalSignificanceTestFactory)();

template <typename T>
QStringList toStringList( const std::vector<T*> & v )
{
    QStringList result;
    for( unsigned i = 0; i < v.size(); i++ )
	result << v[i]->name();

    return( result );
}

MOOPerformanceAssessmentConfig::MOOPerformanceAssessmentConfig()
{
    m_dataSetReader 	= 0;
    m_fileNameAssembler = 0;

    m_noObjectives 	= -1;
    m_trials 		= -1;
    m_generations 	= -1;
}

std::string MOOPerformanceAssessmentConfig::monitor()
{
    std::stringstream stream;

    stream << "Parameter Setting:" 										<< std::endl;
    stream << "\tDataDir		= " << m_dataDir.toStdString() 						<< std::endl;
    stream << "\tResultDir		= " << m_dataDir.toStdString() 						<< std::endl;
    stream << "\tAlgorithms		= " << m_algorithms.join( "," ).toStdString() 				<< std::endl;
    stream << "\tFunctions		= " << m_functions.join( "," ).toStdString() 				<< std::endl;
    stream << "\tNo Objectives		= " << m_noObjectives							<< std::endl;
    stream << "\tNo Trials		= " << m_trials								<< std::endl;
    stream << "\tNo Generations		= " << m_generations							<< std::endl;
    stream << "\tPostProcessors		= " << toStringList( m_vPostProcessors ).join( "," ).toStdString() 	<< std::endl;
    stream << "\tDataSetReader		= " << qPrintable( m_dataSetReader->name() )				<< std::endl;
    stream << "\tFileNameAssembler 	= " << qPrintable( m_fileNameAssembler->name() ) 			<< std::endl;

    return( stream.str() );
}

bool MOOPerformanceAssessmentConfig::load( const QString & uri )
{
    QSettings settings( uri, QSettings::IniFormat );
   
    QString dllURI = settings.value( "DataSetReader" ).toString();
    DataSetReaderFactory dataSetReaderFactory = (DataSetReaderFactory) QLibrary::resolve( dllURI, "factory" );
    if( !CHECK_NULL( dataSetReaderFactory ) )
	{
	    m_dataSetReader = dataSetReaderFactory();
	}
    else
	qDebug( "factory couldn't be found in %s", qPrintable( dllURI ) );

    dllURI = settings.value( "FileNameAssembler" ).toString();
    FileNameAssemblerFactory fileNameAssemblerFactory = (FileNameAssemblerFactory) QLibrary::resolve( dllURI, "factory" );
    if( !CHECK_NULL( fileNameAssemblerFactory ) )
	{
	    m_fileNameAssembler = fileNameAssemblerFactory();
	}
    else
	qDebug( "factory couldn't be found in %s", qPrintable( dllURI ) );
 
    m_dataDir 		= settings.value( "DataDir" ).toString();
    m_resultDir 	= settings.value( "ResultDir" ).toString();
    
    m_algorithms 	= settings.value( "Algorithms" ).toString().split( " " ); 
    m_functions 	= settings.value( "Functions" ).toString().split( " " );

    m_noObjectives	= settings.value( "NoObjectives" ).toInt();
    m_trials		= settings.value( "Trials" ).toInt();
    m_generations	= settings.value( "Generations" ).toInt();

    QStringList sl = settings.value( "Indicators" ).toString().split( " " );
    m_vIndicators.clear();
    for( int i = 0; i < sl.size(); i++ )
	{
	    BinaryQualityIndicatorFactory factory = (BinaryQualityIndicatorFactory) QLibrary::resolve( sl.at( i ), "factory" );

	    if( CHECK_NULL( factory ) )
		continue;

	    IBinaryQualityIndicator * indicator = factory();

	    if( CHECK_NULL( indicator ) )
		continue;

	    m_vIndicators.push_back( indicator );
	}

    sl = settings.value( "StatisticalSignificanceTests" ).toString().split( " " );
    m_vSignificanceTests.clear();
    for( int i = 0; i < sl.size(); i++ )
	{
	    StatisticalSignificanceTestFactory factory = (StatisticalSignificanceTestFactory) QLibrary::resolve( sl.at( i ), "factory" );
	    
	    if( CHECK_NULL( factory ) )
		continue;

	    IStatisticalSignificanceTest * test = factory();

	    if( CHECK_NULL( test ) )
		continue;

	    m_vSignificanceTests.push_back( test );
	}

    sl = settings.value( "PostProcessors" ).toString().split( " " );
    m_vPostProcessors.clear();
    for( int i = 0; i < sl.size(); i++ )
	{
	    IPostProcessorFactory factory = (IPostProcessorFactory) QLibrary::resolve( sl.at( i ), "factory" );
	    
	    if( CHECK_NULL( factory ) )
		continue;

	    IPostProcessor * test = factory();

	    if( CHECK_NULL( test ) )
		continue;

	    m_vPostProcessors.push_back( test );
	}

    sl = settings.value( "ReferencePoint" ).toString().split( " " );
    m_referencePoint.resize( sl.size() );	
    for( int i = 0; i < sl.size(); i++ )
	m_referencePoint[i] = sl.at( i ).toDouble();

    return( true );
}
